package com.zhs.base.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zhs.base.config.properties.AMapProperties;
import com.zhs.base.dto.GeoCodeDto;
import com.zhs.base.dto.GeoInfoDto;
import com.zhs.base.service.BaseMapApiService;
import com.zhs.base.service.MapApiService;
import com.zhs.base.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.util.Objects;

/**
 * 高德
 *
 * @author Java架构师之旅
 * @version 1.0
 * @date 2022年08月16日 17:15.
 */
@Slf4j
public class AMapMapApiService extends BaseMapApiService implements MapApiService {
    private AMapProperties aMapProperties;

    public void setAMapProperties(final AMapProperties aMapProperties) {
        this.aMapProperties = aMapProperties;
    }

    @Override
    public GeoCodeDto getGeocode(String address) {
        log.info("【地址编码 高德】入参: address={}", address);
        try {
            String getGeocoderLatitudeUrl = getGeocoderLatitudeMapUrl(super.encode(address));
            return dealReturnJson(HttpClientUtils.get(getGeocoderLatitudeUrl));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private GeoCodeDto dealReturnJson(final String str) throws RuntimeException {
        JSONObject jsonObject = JSON.parseObject(str);
        String status = jsonObject.getString("status");
        if (Objects.equals(NumberUtils.INTEGER_ONE, Integer.valueOf(status))) {// 1 表示查询成功
            JSONArray arr = JSON.parseArray(jsonObject.getString("geocodes"));
            JSONObject obj = JSON.parseObject(arr.getString(0));
            String location = obj.getString("location");
            final GeoCodeDto geoCodeDto = new GeoCodeDto();
            geoCodeDto.setLng(location.split(",")[0]);
            geoCodeDto.setLat(location.split(",")[1]);
            log.info("【地址编码】 成功 geoCodeDto={}", JSON.toJSONString(geoCodeDto));
            return geoCodeDto;
        }
        log.warn("【地址编码】 失败 status={} | info={}", status, jsonObject.getString("info"));
        throw new RuntimeException(jsonObject.getString("info"));
    }

    private String getGeocoderLatitudeMapUrl(final String address) {
        return this.aMapProperties.getAMapGeoUrl() + address + "&key=" + aMapProperties.getAMapKey();
    }

    @Override
    public GeoInfoDto getAddress(final GeoCodeDto geoCodeDto) {
        log.info("【高德逆地址编码】入参,geoCodeDto={}", JSON.toJSONString(geoCodeDto));
        String urlString = getAddressUrl(geoCodeDto.getLng(), geoCodeDto.getLat());
        try {
            final GeoInfoDto res = dealReturnAddJson(HttpClientUtils.get(urlString));
            log.info("【逆地址编码】res={}", res);
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    private GeoInfoDto dealReturnAddJson(final String res) throws RuntimeException {
        if (StringUtils.isNotBlank(res)) {
            JSONObject jsonObject = JSON.parseObject(res);
            String status = jsonObject.getString("status");
            if (Objects.equals(NumberUtils.INTEGER_ONE, Integer.valueOf(status))) {
                JSONObject jsonObject_ = JSON.parseObject(jsonObject.getString("regeocode"));
                String formatted_address = jsonObject_.getString("formatted_address");
                final GeoInfoDto geoInfoDto = new GeoInfoDto();
                geoInfoDto.setAddress(formatted_address);
                JSONObject addressJsonObject = JSON.parseObject(jsonObject_.getString("addressComponent"));
                if (null != addressJsonObject) {
                    geoInfoDto.setProvince(addressJsonObject.getString("province"));
                    geoInfoDto.setCity(addressJsonObject.getString("city"));
                    geoInfoDto.setDistrict(addressJsonObject.getString("district"));
                    geoInfoDto.setTownship(addressJsonObject.getString("township"));
                    final JSONObject streetNumber = JSON.parseObject(addressJsonObject.getString("streetNumber"));
                    if (null != streetNumber) {
                        geoInfoDto.setStreet(streetNumber.getString("street"));
                        geoInfoDto.setStreetNumber(streetNumber.getString("number"));
                    }
                    log.info("【逆地址编码】 成功 geoInfoDto={}", JSON.toJSONString(geoInfoDto));
                }
                return geoInfoDto;
            } else {
                log.warn("【逆地址编码】 失败 status={} | info={}", status, jsonObject.getString("info"));
                throw new RuntimeException(jsonObject.getString("info"));
            }
        }
        return null;
    }

    private String getAddressUrl(final String lng, final String lat) {
        return aMapProperties.getAMapReGeoUrl() + lng + "," + lat + "&key=" + aMapProperties.getAMapKey();
    }

    @Override
    public Integer getWeight() {
        return aMapProperties.getWeight();
    }
}
